/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.anproc.registery;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import org.mvel2.templates.CompiledTemplate;
import org.mvel2.templates.TemplateCompiler;
import org.mvel2.templates.TemplateRuntime;
import org.openide.util.lookup.ServiceProvider;

/**
 *
 * @author User
 */
@SupportedAnnotationTypes("bgu.anproc.registery.Register")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@ServiceProvider(service = Processor.class)
public class CompileTimeRegistrationProcessor extends AbstractProcessor {

    boolean worked = false;

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (worked) {
            return true;
        }
        worked = true;

        try {
            CompiledTemplate template = TemplateCompiler.compileTemplate(getClass().getResourceAsStream("GlobalRegistration.tpl"));
            Map context = new HashMap();
            List singletones = new LinkedList();
            for (Element elem : roundEnv.getElementsAnnotatedWith(Register.class)) {
                TypeElement telem = (TypeElement) elem;
                Register r = elem.getAnnotation(Register.class);
                String message = "registery annotation found in " + elem.getSimpleName();
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message);

                if (r.singleton()) {
                    singletones.add(new SingletonItemDescriptor().setName(extractName(r, telem)).setIconPath(extractIconPath(r, telem)).setDescription(extractDescription(r, telem)).setItemClass(telem.getQualifiedName().toString()));
                }
            }

            context.put("singletones", singletones);
            JavaFileObject jfo = processingEnv.getFiler().createSourceFile(
                    "bgu.anproc.registery.GlobalRegistration");
            try (OutputStream out = jfo.openOutputStream()) {
                TemplateRuntime.execute(template, context, out);
            }
            

        } catch (IOException ex) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, ex.getMessage() + "@" + ex.getClass().getSimpleName());
        }
        return true; // no further processing of this annotation type
    }

    private String extractName(Register r, TypeElement telem) {
        if (r.name().isEmpty()) {
            return telem.getSimpleName().toString();
        } else {
            return r.name();
        }
    }

    private String extractIconPath(Register r, TypeElement telem) {
        return r.iconPath();
    }

    private String extractDescription(Register r, TypeElement telem) {
        return r.description();
    }
}
